package com.liang.blog.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import com.liang.blog.common.exception.BlogException;
import com.liang.blog.common.result.ResultCodeEnum;
import com.liang.blog.file.utils.ConstantOssPropertiesUtils;
import com.liang.blog.service.BlogFileService;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.UUID;

/**
 * @Author：YanWenLiang
 * @Date:2023-09-08-20:32
 */
@Service
@Slf4j
public class BlogFileServiceImpl implements BlogFileService {

    @Value("${server.port}")
    private String port;

    @Value("${file.ip}")
    private String ip;

    /**
     * 上传头像
     * @param file
     * @return
     */
    @Override
    public String uploadAvatar(MultipartFile file) {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String holder = "blog/avatar/" + uuid;
        String path = this.upload(file, holder);
        return path;
    }

    @Override
    public String uploadFileImg(MultipartFile file) {
        return null;
    }

    /**
     * 本地文件上传接口
     * @param file
     * @return
     */
    @Override
    public String uploadLocal(MultipartFile file, String folder) {
        if (ObjectUtil.isEmpty(file)){
            throw new BlogException("上传的文件损坏，请重新上传！", ResultCodeEnum.DATA_ERROR.getCode());
        }

        String originalFilename = file.getOriginalFilename();  // 获取源文件的名称
        // 定义文件的唯一标识（前缀）
        String flag = IdUtil.fastSimpleUUID();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        String filePath = "\\service\\service-file\\files\\" + folder + "\\" + flag + "." + substring;
        String rootFilePath = System.getProperty("user.dir") + filePath;  // 获取上传的路径
        File saveFile = new File(rootFilePath);
        if (!saveFile.getParentFile().exists()) {
            saveFile.getParentFile().mkdirs();
        }
        try {
            FileUtil.writeBytes(file.getBytes(), rootFilePath);  // 把文件写入到上传的路径
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "http://" + ip + ":" + port + "/" + folder + "/" + flag + "." + substring;
    }

    /**
     * 本地下载接口
     * @param flag
     * @param response
     */
    @Override
    public void getFiles(String folder, String flag, HttpServletResponse response) {
        // 新建一个输出流对象
        String basePath = System.getProperty("user.dir") + "\\service\\service-file\\files\\" + folder;  // 定于文件上传的根路径
        List<String> fileNames = FileUtil.listFileNames(basePath);  // 获取所有的文件名称
        String fileName = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");  // 找到跟参数一致的文件
        try(OutputStream os = response.getOutputStream()) {
            if (StrUtil.isNotEmpty(fileName)) {
                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                response.setContentType("application/octet-stream");
                byte[] bytes = FileUtil.readBytes(basePath + "\\" + fileName);  // 通过文件的路径读取文件字节流
                os.write(bytes);
                os.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
           log.error("文件下载失败");
        }
    }

    /**
     * 删除头像
     * @param fileName
     * @return
     */
    @Override
    public void deleteAvatar(String fileName) {
        this.delete("blog/avatar/" + fileName);
    }

    public void delete(String path){
        // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
        String endpoint = ConstantOssPropertiesUtils.ENDPOINT;
        String keyId = ConstantOssPropertiesUtils.ACCESS_KEY_ID;
        String secret = ConstantOssPropertiesUtils.SECRECT;
        // 填写Bucket名称，例如examplebucket。
        String bucketName = ConstantOssPropertiesUtils.BUCKET;
        // 填写文件完整路径。文件完整路径中不能包含Bucket名称。
        String objectName = path;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyId, secret);

        try {
            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(bucketName, objectName);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    public String upload(MultipartFile file, String holder) {
        // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
        String endpoint = ConstantOssPropertiesUtils.ENDPOINT;
        String keyId = ConstantOssPropertiesUtils.ACCESS_KEY_ID;
        String secret = ConstantOssPropertiesUtils.SECRECT;
        // 填写Bucket名称，例如examplebucket。
        String bucketName = ConstantOssPropertiesUtils.BUCKET;
        String objectName = holder + file.getOriginalFilename();

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyId, secret);

        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file.getInputStream());
//             如果需要上传时设置存储类型和访问权限，请参考以下示例代码。
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);

            putObjectRequest.setMetadata(metadata);
            // 上传文件。
            ossClient.putObject(putObjectRequest);
            return "http://" + ConstantOssPropertiesUtils.BUCKET + "."
                    + ConstantOssPropertiesUtils.ENDPOINT + "/" + objectName;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return "";
    }





}
